﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;

namespace psafth.RCTiming.Common
{
    public enum MulticastDataType : byte
    {
        HeatObject = 0x01,
        Competitors = 0x02,
        Start = 0x03,
        Pause = 0x04,
        Stop = 0x05,
        NoRace = 0x06
    }

    public class MulticastHelper
    {
        // Convert an object to a byte array
        public static byte[] ObjectToByteArray(object obj)
        {
            if (obj == null)
                return null;
            BinaryFormatter bf = new BinaryFormatter();
            using (MemoryStream ms = new MemoryStream())
            {
                bf.Serialize(ms, obj);
                return ms.ToArray();
            }
        }

        public static byte[] ObjectToByteArray(object obj, byte type)
        {
            if (obj == null)
                return null;

            byte[] startVal;
            byte[] dataVal;

            BinaryFormatter bf = new BinaryFormatter();

            using (MemoryStream ms = new MemoryStream())
            {
                bf.Serialize(ms, obj);
                startVal = new byte[] { type };
                dataVal = ms.ToArray();
            }

            byte[] sum = new byte[startVal.Length + dataVal.Length];

            startVal.CopyTo(sum, 0);
            dataVal.CopyTo(sum, startVal.Length);

            return sum;
        }

        /// <summary>
        /// Function to get object from byte array
        /// </summary>
        /// <param name="byteArray">byte array to get object</param>
        /// <returns>object</returns>
        public static object ByteArrayToObject(byte[] byteArray)
        {
            try
            {

                byte[] data = byteArray.Skip(1).ToArray();
                // convert byte array to memory stream
                using (MemoryStream memoryStream = new MemoryStream(data))
                {
                    // create new BinaryFormatter
                    System.Runtime.Serialization.Formatters.Binary.BinaryFormatter binaryFormatter
                                = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

                    // set memory stream position to starting point
                    memoryStream.Position = 0;

                    // Deserializes a stream into an object graph and return as a object.
                    switch (byteArray[0])
                    {
                        case (byte)MulticastDataType.HeatObject:
                            return (HeatCommand)binaryFormatter.Deserialize(memoryStream);

                        case (byte)MulticastDataType.Competitors:
                            return (List<MCDriver>)binaryFormatter.Deserialize(memoryStream);

                        case (byte)MulticastDataType.Start:
                            return (StartCommand)binaryFormatter.Deserialize(memoryStream);

                        case (byte)MulticastDataType.Pause:
                            return (PauseCommand)binaryFormatter.Deserialize(memoryStream);

                        case (byte)MulticastDataType.Stop:
                            return (StopCommand)binaryFormatter.Deserialize(memoryStream);

                        case (byte)MulticastDataType.NoRace:
                            return null;
                    }
                }
            }
            catch (Exception ex)
            {
                // Error
                Console.WriteLine("Exception caught in process: {0}", ex.ToString());
            }

            // Error occured, return null
            return null;
        }
    }
}
